#include <vlGraphics/GeometryPrimitives.hpp>
#include <vlGraphics/SceneManagerActorTree.hpp>
#include <vlGraphics/Actor.hpp>
#include <vlGraphics/Effect.hpp>
#include "MyApplet.hpp"

void MyApplet::initViews()
{
    vl::ref<vl::RenderTarget> rt = getRendering()->renderer()->renderTarget();
    vl::EReadDrawBuffer rdb = rt->drawBuffers()[0];
    vl::ref<vl::ReadPixels> readPix = new vl::ReadPixels(0, 0, rt->width(),
        rt->height(), rdb, 0, false);
    readPix->setSavePath("test.png");
    readPix->setRemoveAfterCall(true);
    rendering()->onFinishedCallbacks()->push_back(readPix.get());
    //rvRight.get()->setScreenBuffer(readPix);
}

void MyApplet::updateEvent()
{
    if (sface.get_update())
    {
        sface.reset_update();

        openglContext()->setContinuousUpdate(true);

        // reset actors
        sceneManager()->tree()->actors()->clear();

        if (sface.is_raytracing())
        {
            // moze obeszloby sie bez tych 4 linijek
            mDraw->releaseImages();

            vl::ref<vl::DrawPixels::Pixels> pix;
            pix = new vl::DrawPixels::Pixels(sface.get_image().get(), 0, 0);

            mDraw->draws()->push_back(pix.get());

            //mDraw->generatePixelBufferObjects(vl::GBU_STATIC_DRAW, true);

            vl::ref<vl::Actor> actor = new vl::Actor(mDraw.get(), new vl::Effect);

            // effect
            //actor->effect()->shader()->setRenderState(new vl::Light(0));
            //actor->effect()->shader()->enable(vl::EN_DEPTH_TEST);
            //actor->effect()->shader()->enable(vl::EN_LIGHTING);
            //actor->effect()->shader()->gocLightModel()->setTwoSide(true);
            //actor->effect()->shader()->gocMaterial()->setBackDiffuse(vlut::green);

            sceneManager()->tree()->addActor(actor.get());
        }
        else
        {
            mVolume->setup(sface.get_voxels(), vl::fvec3(-5,-5,-5), vl::fvec3(+5,+5,+5), vl::ivec3(sface.get_width(), sface.get_height(), sface.get_depth()));

            mMarchingCubes.reset();
            mMarchingCubes.volumeInfo()->push_back(new vl::VolumeInfo(mVolume.get(), mThreshold));

            // run MarchingCubes with timing.
            mMarchingCubes.run(true);

            // setup isosurface geometry, actor and effect

            // geometry
            vl::ref<vl::Geometry> isosurf_geom = new vl::Geometry;
            // disable VBO since we update the vertices every frame
            isosurf_geom->setVBOEnabled(false);
            // install vertex and normal arrays and primitives generated by the marching cube algorithm
            isosurf_geom->setVertexArray(mMarchingCubes.mVertsArray.get());
            isosurf_geom->setNormalArray(mMarchingCubes.mNormsArray.get());
            isosurf_geom->drawCalls()->push_back(mMarchingCubes.mDrawElements.get());

            // actor
            vl::ref<vl::Actor> actor = new vl::Actor(isosurf_geom.get(), new vl::Effect);

            // effect
            actor->effect()->shader()->setRenderState(new vl::Light(0));
            actor->effect()->shader()->enable(vl::EN_DEPTH_TEST);
            actor->effect()->shader()->enable(vl::EN_LIGHTING);
            actor->effect()->shader()->gocLightModel()->setTwoSide(true);
            actor->effect()->shader()->gocMaterial()->setBackDiffuse(vl::green);

            // add actor to the scene
            sceneManager()->tree()->addActor(actor.get());
        }

        if (rvRight.get() != 0)
        {
            //getRendering()->camera()->setViewMatrix(rvRight.get()->getInvViewMatrix());
            //Applet::updateEvent();
        }
    }
    vl::ref<vl::Rendering> mainRendering = getRendering();
    vl::mat4 view_mat = vl::mat4::getLookAt(sface.eye(), sface.center(), sface.up()).getInverse();
    mainRendering->camera()->setViewMatrix(view_mat);
    Applet::updateEvent();

    /*if (!sface.is_raytracing())
    {
        std::vector<vl::ref<vl::Rendering> >::iterator it = mCustomRenderings.begin();
        for (; it != mCustomRenderings.end(); it++)
        {
            setRendering((*it).get());
            Applet::updateEvent();
        }
    }
    setRendering(mainRendering.get());*/
}

void MyApplet::updateEvent(vl::ref<vl::Rendering> _rendering)
{
}

vl::ref<vl::Rendering> MyApplet::addRendering()
{
    vl::ref<vl::Rendering> rend = new vl::Rendering;
    rend->sceneManagers()->push_back(sceneManager());
    mCustomRenderings.push_back(rend);
    return rend;
}

void MyApplet::removeRendering(vl::ref<vl::Rendering> _rendering)
{
    std::vector<vl::ref<vl::Rendering> >::iterator it = mCustomRenderings.begin();
    for (; it != mCustomRenderings.end(); it++)
    {
        if ((*it).get() == _rendering.get())
        {
            mCustomRenderings.erase(it);
            return;
        }
    }
}
